home *** CD-ROM | disk | FTP | other *** search
- /*
- * http_script: keeps all script-related ramblings together.
- *
- * Compliant to CGI/1.0 spec
- *
- * Rob McCool
- *
- */
-
- #include "httpd.h"
-
- #ifdef AMIGA
- #include <dos/dos.h>
- #include <dos/dostags.h>
- #endif
-
- char **create_argv(char *av0, char *args) {
- register int x,n;
- char **av;
- char w[MAX_STRING_LEN];
- char l[MAX_STRING_LEN];
-
- for(x=0,n=2;args[x];x++)
- if(args[x] == '+') ++n;
-
- av = (char **)malloc((n+1)*sizeof(char *));
- av[0] = av0;
- strcpy(l,args);
- for(x=1;x<n;x++) {
- getword(w,l,'+');
- unescape_url(w);
- av[x] = strdup(w);
- }
- av[n] = NULL;
- return av;
- }
-
- void get_path_info(char *path, char *path_args, FILE *out,
- struct stat *finfo)
- {
- register int n,x;
- char t[MAX_STRING_LEN];
-
- path_args[0] = '\0';
-
- n=count_dirs(path);
- for(x=0;x<=n;x++) {
- make_dirstr(path,x+1,t);
- if(!(stat(t,finfo))) {
- if(S_ISREG(finfo->st_mode)) {
- strcpy(path_args,&path[strlen(t)]);
- strcpy(path,t);
- return;
- }
- }
- }
- unmunge_name(path);
- die(NOT_FOUND,path,out);
- }
-
- #ifndef NO_CGI_SCRIPTS
-
- void exec_cgi_script(char *method, char *path, char *args, int in, FILE *out)
- {
- int pid, p[2];
- int content, nph;
- char cl[MAX_STRING_LEN],t[MAX_STRING_LEN],t2[MAX_STRING_LEN];
- char path_args[MAX_STRING_LEN];
- char *argv0;
- FILE *psin;
- struct stat finfo;
-
- get_path_info(path,path_args,out,&finfo);
-
- if(!can_exec(&finfo)) {
- unmunge_name(path);
- die(FORBIDDEN,path,out);
- }
-
- /* BAD -- method specific */
- evaluate_access(path,&finfo,((!strcmp(method,"POST")) ? M_POST : M_GET),
- &allow,&allow_options);
- if(!allow) {
- log_reason("client denied by server configuration",path);
- unmunge_name(path);
- die(FORBIDDEN,path,out);
- }
-
- ht_putenv("SERVER_SOFTWARE",SERVER_VERSION);
- ht_putenv("SERVER_NAME",server_hostname);
- ht_putenv("GATEWAY_INTERFACE","CGI/1.0");
-
- sprintf(t,"%d",port);
- ht_putenv("SERVER_PORT",t); /* we only listen to one port */
-
- ht_putenv("SERVER_PROTOCOL",(assbackwards ? "HTTP/0.9" : "HTTP/1.0"));
- ht_putenv("REQUEST_METHOD",method);
- ht_putenv("HTTP_ACCEPT",http_accept);
- if(path_args[0]) {
- ht_putenv("PATH_INFO",path_args);
- strcpy(t2,path_args);
- translate_name(t2,out);
- ht_putenv("PATH_TRANSLATED",t2);
- }
- strcpy(t,path);
- unmunge_name(t);
- ht_putenv("SCRIPT_NAME",t);
- ht_putenv("QUERY_STRING",args);
- ht_putenv("REMOTE_HOST",remote_name);
- ht_putenv("REMOTE_ADDR",remote_ip);
- if(user[0])
- ht_putenv("REMOTE_USER",user);
- if(auth_type)
- ht_putenv("AUTH_TYPE",auth_type);
-
- content=0;
- if((!strcmp(method,"POST")) || (!strcmp(method,"PUT"))) {
- content=1;
- sprintf(cl,"%d",content_length);
- ht_putenv("CONTENT_TYPE",content_type);
- ht_putenv("CONTENT_LENGTH",cl);
- }
-
- if((argv0 = strrchr(path,'/')) != NULL)
- argv0++;
- else argv0 = path;
-
- #ifndef AMIGA
- if(pipe(p) < 0)
- die(SERVER_ERROR,"httpd: could not create IPC pipe",out);
- if((pid = fork()) < 0)
- die(SERVER_ERROR,"httpd: could not fork new process",out);
-
- nph = (strncmp(argv0,"nph-",4) ? 0 : 1);
- if(!pid) {
- if(content)
- if(in != STDIN_FILENO) {
- dup2(in,STDIN_FILENO);
- close(in);
- }
- if(nph) {
- if(fileno(out) != STDOUT_FILENO) {
- dup2(fileno(out),STDOUT_FILENO);
- dup2(fileno(out),STDERR_FILENO);
- fclose(out);
- }
- } else {
- if(p[1] != STDOUT_FILENO) {
- dup2(p[1],STDOUT_FILENO);
- close(p[1]);
- }
- }
- dup2(STDOUT_FILENO,STDERR_FILENO);
- /* Only ISINDEX scripts get decoded arguments. */
- if((!args[0]) || (ind(args,'=') >= 0)) {
- if(execl(path,argv0,(char *)0) == -1)
- exit(1);
- }
- else
- if(execv(path,create_argv(argv0,args)) == -1)
- exit(1);
- }
- else
- close(p[1]);
- #else
- nph = 0; /* Not yet supported */
-
- {
- ULONG ChildIn;
- ULONG ChildOut;
- char buffer[256];
- char * invoker = "";
-
- if( can_script( &finfo ) )
- invoker = "execute";
- else
- {
- FILE * fh;
-
- if( fh = fopen( path, "r" ) )
- {
- fread( buffer, 3, 1, fh );
- fclose( fh );
-
- if( (buffer[0] == '/' ) && (buffer[1] == '*' ) )
- invoker = "rx";
- }
- }
-
- sprintf( buffer, "%s %s %s", invoker, path, args );
-
- ChildIn = Open( "nil:", MODE_OLDFILE );
- ChildOut = Open( "pipe:http-cgi", MODE_NEWFILE );
-
- if( ChildIn && ChildOut
- && ( SystemTags( buffer, SYS_Asynch, TRUE,
- SYS_Input, ChildIn,
- SYS_Output, ChildOut,
- TAG_DONE ) >= 0 ) )
- {
-
- }
- else
- {
- if( ChildIn ) Close( ChildIn );
- if( ChildOut ) Close( ChildOut );
-
-
- die(SERVER_ERROR,"could not run script",out);
- }
-
- }
-
- #endif
-
- if(!nph) {
- #ifndef AMIGA
- if(!(psin = fdopen(p[0],"r")))
- #else
- if( ! (psin = fopen( "pipe:http-cgi", "r" ) ) )
- #endif
- die(SERVER_ERROR,"could not read from script",out);
-
- if(scan_script_header(psin,out)) {
- escape_url(location);
- die(REDIRECT,location,out);
- }
-
- if(location[0] == '/') {
- char t[MAX_STRING_LEN];
- fclose(psin);
- strcpy(t,location);
- location[0] = '\0';
- process_get(in,out,method,t,NULL);
- return;
- }
- content_length = -1;
- if(!assbackwards)
- send_mime_headers(out);
-
- send_fd(psin,out,args);
- fclose(psin);
- }
- #ifndef AMIGA
- waitpid(pid,NULL,0);
- #endif
- }
-
- #endif
-
- void set_env_NCSA() {
- char *t3;
-
- ht_putenv("DOCUMENT_ROOT",document_root);
- ht_putenv("SERVER_ROOT",server_root);
- ht_putenv("REMOTE_HOST",remote_name);
- t3 = (char *)malloc(strlen("SERVER_NAME=") + strlen(server_hostname) + 6);
- sprintf(t3,"SERVER_NAME=%s:%d",server_hostname,port);
- putenv(t3);
- }
-
- #ifndef NO_NCSA_EXEC
-
- void exec_get_NCSA(char *path, char *args, FILE *fd) {
- FILE *tfp;
- struct stat finfo;
- int pid,pfd[2];
- char path_args[MAX_STRING_LEN];
- char t[MAX_STRING_LEN];
- register int n,x;
-
- set_env_NCSA();
-
- path_args[0] = '\0';
- /* check if it's really a script with extra args */
- n=count_dirs(path);
- for(x=0;x<=n;x++) {
- make_dirstr(path,x+1,t);
- if(!(stat(t,&finfo))) {
- if(S_ISREG(finfo.st_mode)) {
- strcpy(path_args,&path[strlen(t)]);
- strcpy(path,t);
- goto run_script;
- }
- }
- }
- log_reason("script not found or unable to stat",path);
- unmunge_name(path);
- die(NOT_FOUND,path,fd);
- run_script:
- if(!can_exec(&finfo)) {
- log_reason("file permissions deny server execution",path);
- unmunge_name(path);
- die(FORBIDDEN,path,fd);
- }
- evaluate_access(path,&finfo,M_GET,&allow,&allow_options);
- if(!allow) {
- unmunge_name(path);
- die(FORBIDDEN,path,fd);
- }
-
- if(pipe(pfd) < 0)
- die(SERVER_ERROR,"could not open pipe",fd);
-
- #ifndef AMIGA
- signal(SIGALRM,send_fd_timed_out);
- signal(SIGPIPE,send_fd_timed_out);
- #endif
- alarm(timeout);
-
- if((pid = fork()) < 0)
- die(SERVER_ERROR,"could not fork",fd);
- else if(!pid) {
- char *argv0;
-
- close(pfd[0]);
- if(pfd[1] != STDOUT_FILENO) {
- dup2(pfd[1],STDOUT_FILENO);
- close(pfd[1]);
- }
- if(argv0 = strrchr(path,'/'))
- argv0++;
- else
- argv0 = path;
- if(args[0] && path_args[0]) {
- if(execl(path,argv0,path_args,args,(char *)0) == -1)
- exit(1);
- }
- else if(args[0]) {
- if(execl(path,argv0,args,(char *)0) == -1)
- exit(1);
- }
- else if(path_args[0]) {
- if(execl(path,argv0,path_args,(char *)0) == -1)
- exit(1);
- }
- else
- if(execl(path,argv0,(char *)0) == -1)
- exit(1);
- }
- else
- close(pfd[1]);
-
- tfp = fdopen(pfd[0],"r");
-
- if(scan_script_header(tfp,fd)) {
- escape_url(location);
- die(REDIRECT,location,fd);
- }
-
- if(location[0] == '/') {
- char *t = strdup(location);
- location[0] = '\0';
- send_node(t,"",fd);
- exit(0);
- }
-
- if(!assbackwards)
- send_mime_headers(fd);
-
- if(!header_only)
- send_fd(tfp,fd,args);
- fclose(tfp);
- waitpid(pid,NULL,0);
- }
-
-
-
- void exec_post_NCSA(char *path, char *args, int in, FILE *out) {
- int pid, inpipe[2],outpipe[2], x;
- char cl[MAX_STRING_LEN];
- FILE *psin,*psout;
- struct stat finfo;
-
- set_env_NCSA();
-
- sprintf(cl,"%d",content_length);
-
- if(stat(path,&finfo) == -1) {
- unmunge_name(path);
- if(errno == ENOENT) die(NOT_FOUND,path,out);
- die(FORBIDDEN,path,out);
- }
- evaluate_access(path,&finfo,M_POST,&allow,&allow_options);
- if(!allow)
- die(FORBIDDEN,path,out);
-
- if(pipe(inpipe) < 0)
- die(SERVER_ERROR,"httpd: could not create IPC pipe",out);
- if(pipe(outpipe) < 0)
- die(SERVER_ERROR,"httpd: could not create IPC pipe",out);
- if((pid = fork()) < 0)
- die(SERVER_ERROR,"httpd: could not fork new process",out);
-
- if(!pid) {
- char *argv0;
-
- if(outpipe[1] != STDOUT_FILENO) {
- dup2(outpipe[1],STDOUT_FILENO);
- close(outpipe[1]);
- }
- if(in != STDIN_FILENO) {
- dup2(in,STDIN_FILENO);
- close(in);
- }
- if((argv0 = strrchr(path,'/')) != NULL)
- argv0++;
- else argv0 = path;
- if(execlp(path,argv0,cl,args,(char *)0) == -1)
- exit(1);
- }
- else {
- close(outpipe[1]);
- close(inpipe[0]);
- }
-
- if(!(psin = fdopen(outpipe[0],"r")))
- die(SERVER_ERROR,"could not read from script",out);
-
- if(scan_script_header(psin,out)) {
- escape_url(location);
- die(REDIRECT,location,out);
- }
- content_length = -1;
- if(!assbackwards) {
- /* fstat(f,&finfo); */
- /* set_content_length(finfo.st_size); */
- /* set_last_modified(finfo.st_mtime); */
- send_mime_headers(out);
- }
-
- send_fd(psin,out,args);
- fclose(psin);
- waitpid(pid,NULL,0);
- }
-
- #endif
-